Skip to content

Add mTLS auth modal and validation#628

Open
marcschwaiger wants to merge 2 commits intonetbirdio:mainfrom
marcschwaiger:feature/mtls-auth
Open

Add mTLS auth modal and validation#628
marcschwaiger wants to merge 2 commits intonetbirdio:mainfrom
marcschwaiger:feature/mtls-auth

Conversation

@marcschwaiger
Copy link
Copy Markdown

@marcschwaiger marcschwaiger commented May 1, 2026

Issue ticket number and link

netbirdio/netbird#5364 mTLS Auth for Proxy Services

Documentation

Select exactly one:

  • I added/updated documentation for this change
  • Documentation is not needed for this change (explain why)

Docs PR URL (required if "docs added" is checked)

Paste the PR link from https://github.com/netbirdio/docs here:

netbirdio/docs#720

See also: Netbird PR URL

netbirdio/netbird#6048

Summary by CodeRabbit

  • New Features
    • Added mutual TLS (mTLS) authentication option with enable/disable controls for reverse-proxy.
    • Support for entering or uploading CA certificate PEM with strict format validation.
    • UI for managing mTLS (enable, save, remove) including masked PEM handling.
    • Visual mTLS indicators shown in authentication views and event displays.
    • Validation blocks progression when mTLS is enabled but PEM is missing.

@CLAassistant
Copy link
Copy Markdown

CLAassistant commented May 1, 2026

CLA assistant check
All committers have signed the CLA.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 1, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: cfafc495-a26a-454d-913c-46e68776df07

📥 Commits

Reviewing files that changed from the base of the PR and between 68d0daf and 7d969ec.

📒 Files selected for processing (1)
  • src/modules/reverse-proxy/auth/AuthMTLSModal.tsx
✅ Files skipped from review due to trivial changes (1)
  • src/modules/reverse-proxy/auth/AuthMTLSModal.tsx

📝 Walkthrough

Walkthrough

Adds mTLS authentication support to the reverse-proxy UI and types: extends the ReverseProxyAuth interface with mtls_auth, introduces an AuthMTLSModal component to manage CA certificate PEMs (validation, masking, file upload), and updates reverse-proxy modals and auth display cells to surface and persist mTLS settings.

Changes

mTLS reverse-proxy flow

Layer / File(s) Summary
Data Shape
src/interfaces/ReverseProxy.ts
Adds optional mtls_auth?: { enabled: boolean; ca_cert_pem?: string } to ReverseProxyAuth.
Core UI / Validation
src/modules/reverse-proxy/auth/AuthMTLSModal.tsx
New AuthMTLSModal component: masked display, PEM textarea, file upload, validation that each PEM block base64-decodes and begins with 0x30 (X.509), and save/remove handlers.
Wiring / State
src/modules/reverse-proxy/ReverseProxyModal.tsx
Adds state for mtlsEnabled, mtlsCACertPEM, and mtlsModalOpen; integrates modal, blocks continue/submit when mTLS enabled without CA PEM, persists auth.mtls_auth on save/remove.
Display / Badges
src/modules/reverse-proxy/events/ReverseProxyEventsAuthMethodCell.tsx, src/modules/reverse-proxy/table/ReverseProxyAuthCell.tsx
Recognizes mtls / mtls_auth as an auth method, adds ShieldCheckIcon and label “mTLS”, and includes mTLS in enabled-method badge/hover logic.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • pascal-fischer
  • lixmal

Poem

🐰 I nibble keys and hop through code,
CA PEMs tucked in a cozy node.
Modal opens, certificates gleam,
mTLS snug in the security stream.
Hooray — I bounce, commit, and goad!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main changes: adding mTLS authentication modal and validation logic across multiple files.
Description check ✅ Passed The description includes issue reference, documentation status with PR link, and related PR link, meeting all required template sections.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
Review rate limit: 7/8 reviews remaining, refill in 7 minutes and 30 seconds.

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
src/modules/reverse-proxy/ReverseProxyModal.tsx (1)

342-349: 💤 Low value

The canReuseStoredMTLSCert guard is sound, but the implicit contract deserves a comment

The logic correctly handles the "cert stored server-side, not echoed back" case: submitting { enabled: true, ca_cert_pem: undefined } tells the backend to preserve the stored cert. This is the right design, but a brief inline comment would help future maintainers understand why mtlsError is suppressed when the PEM string is empty.

💡 Suggested inline comment
+ // If the proxy was already configured with mTLS, the backend holds the cert and
+ // won't return it — submitting ca_cert_pem: undefined preserves the stored cert.
  const canReuseStoredMTLSCert =
    reverseProxy?.auth?.mtls_auth?.enabled === true;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/modules/reverse-proxy/ReverseProxyModal.tsx` around lines 342 - 349, Add
a short inline comment above the canReuseStoredMTLSCert / mtlsError logic
explaining the implicit contract: when reverseProxy?.auth?.mtls_auth?.enabled is
true and the server has a stored cert, submitting ca_cert_pem as an empty string
(mtlsCACertPEM.trim().length === 0) signals “preserve server-side cert,” so
mtlsError should be suppressed; reference the canReuseStoredMTLSCert,
mtlsEnabled, mtlsCACertPEM, and mtlsError symbols to clarify why an empty PEM is
allowed and not treated as a validation failure.
src/modules/reverse-proxy/auth/AuthMTLSModal.tsx (1)

112-121: ⚡ Quick win

No error handler on FileReader — silent failure on read error

If readAsText fails (e.g., filesystem permission denied, corrupted file), the user gets no feedback.

🛠 Suggested fix
  fileReader.readAsText(file, "UTF-8");
  fileReader.onload = (e) => {
    if (e.target === null) return;
    handleFileText(e.target.result as string);
  };
+ fileReader.onerror = () => {
+   // surface a user-visible error if needed, or at minimum log
+   console.error("Failed to read certificate file");
+ };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/modules/reverse-proxy/auth/AuthMTLSModal.tsx` around lines 112 - 121,
handleFileUpload currently uses FileReader.readAsText without any error handling
so read failures are silent; add a FileReader.onerror (and optionally
onabort/onloadend) handler that captures the FileReader.error and surfaces it
(e.g., call an existing error handler or set an error state) and ensure
handleFileText is only called on successful load inside onload; update the
FileReader usage in handleFileUpload to attach fileReader.onerror and propagate
a clear error message referencing FileReader.error and the file name so the UI
can show feedback.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/modules/reverse-proxy/auth/AuthMTLSModal.tsx`:
- Around line 159-187: The upload container in AuthMTLSModal is not
keyboard-accessible; update the clickable div to be focusable and operable by
keyboard by adding tabIndex={0}, role="button", and an onKeyDown handler that
triggers inputRef.current?.click() when Enter or Space is pressed, and include
an accessible label (aria-label or aria-labelledby) describing the action; also
ensure the hidden file input (referenced by inputRef and used by
handleFileUpload) is not removed from interaction (replace the "hidden"
display:none class with a visually-hidden/sr-only technique or ensure the div's
keyboard handler reliably opens the file dialog) so keyboard-only users can open
the file picker.
- Around line 48-53: The leftover check in AuthMTLSModal rejects valid annotated
PEM bundles because comment/header lines (e.g., lines starting with "#" or other
non-PEM annotation lines) remain in trimmed before building leftover; preprocess
the input before the existing certificate-strip step by removing or filtering
out annotation lines (e.g., split trimmed into lines and drop lines that start
with "#" or that don't start with "-----") then rejoin to form trimmed for the
existing replace logic, and keep the subsequent leftover length check as-is
(adjust the error message in the same block if you prefer to mention unsupported
comment lines); refer to the variables/functions AuthMTLSModal, trimmed,
leftover in your changes.

---

Nitpick comments:
In `@src/modules/reverse-proxy/auth/AuthMTLSModal.tsx`:
- Around line 112-121: handleFileUpload currently uses FileReader.readAsText
without any error handling so read failures are silent; add a FileReader.onerror
(and optionally onabort/onloadend) handler that captures the FileReader.error
and surfaces it (e.g., call an existing error handler or set an error state) and
ensure handleFileText is only called on successful load inside onload; update
the FileReader usage in handleFileUpload to attach fileReader.onerror and
propagate a clear error message referencing FileReader.error and the file name
so the UI can show feedback.

In `@src/modules/reverse-proxy/ReverseProxyModal.tsx`:
- Around line 342-349: Add a short inline comment above the
canReuseStoredMTLSCert / mtlsError logic explaining the implicit contract: when
reverseProxy?.auth?.mtls_auth?.enabled is true and the server has a stored cert,
submitting ca_cert_pem as an empty string (mtlsCACertPEM.trim().length === 0)
signals “preserve server-side cert,” so mtlsError should be suppressed;
reference the canReuseStoredMTLSCert, mtlsEnabled, mtlsCACertPEM, and mtlsError
symbols to clarify why an empty PEM is allowed and not treated as a validation
failure.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 3f4bd30a-2c97-42c5-bf48-56dabd662b75

📥 Commits

Reviewing files that changed from the base of the PR and between d76cbd1 and 68d0daf.

📒 Files selected for processing (5)
  • src/interfaces/ReverseProxy.ts
  • src/modules/reverse-proxy/ReverseProxyModal.tsx
  • src/modules/reverse-proxy/auth/AuthMTLSModal.tsx
  • src/modules/reverse-proxy/events/ReverseProxyEventsAuthMethodCell.tsx
  • src/modules/reverse-proxy/table/ReverseProxyAuthCell.tsx

Comment thread src/modules/reverse-proxy/auth/AuthMTLSModal.tsx
Comment thread src/modules/reverse-proxy/auth/AuthMTLSModal.tsx
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants